/*!  \file  SteQR.cpp
 *	  \brief  
 * 
 *   \details   details
 *   \author    Yordan Madzhunkov German Research School for Simulation Sciences GmbH
 *   \version   1.0
 *   \date      06/29/2013 11:11:36 PM
 *   \copyright GNU Public License.
 */
#include "SteQR.h"
#include "Matrix.h"
#include "setThreads.h"
extern "C" {
void dsteqr_(
const char   * jobz, 
const int    * n, 
double * d, 
double * e, 
double * z,
const int    * ldz,
double * work, // size = 2N - 2
int    * info);
}
SteQR::SteQR(): TriEigen( "Lapack dsteqr" ) {	
	setCompileTime(__DATE__, __TIME__); 
	canBeParallel = true;
}
bool SteQR::setNumberOfThreads(int nThreads_) {	
	assert(canBeParallel);
	SET_NUM_THREADS(nThreads_);
	nThreads = nThreads;
	return true;
}
void SteQR::compute(const Matrix & T, Matrix & Sigma, Matrix & Q ){
	reset();
	if (!T.isTriDiagonal()) return;
	assert(T.isTriDiagonal() && Sigma.isDiagonal() && Q.isOrthogonal());
	char jobz = 'I'; Q.makeIdentity();
	int n = T.cols(), info = -1;
	int lwork = min(2 * n ,1);
	double * e = NULL, *work = NULL;
	maxMemory = 0; extraMemory = 0; allocate(e, n); allocate(work, lwork);
	double * d = Sigma.getModData();
	memcpy(d, T.getData()    ,    n * sizeof(*d));
	memcpy(e, T.getOffDiagonal(), (n-1)* sizeof(*d));
	int ldq = Q.lda();	Q.makeColMajor();// Q.makeOrthogonal();
	dsteqr_(&jobz, &n, d, e, Q.getModData(), &ldq, work, &info);
	success &= info == 0;
	delocate(e); delocate(work);
};
BiNESteQR::BiNESteQR() : BiSVD( "NE dsteqr" ) {
	aUpper = true; 
	aLower = true; 
	aUColMajor = true; 
	aVColMajor = true; 
	eigen = new SteQR(); 
	setCompileTime(__DATE__, __TIME__); 
	if (eigen) setCompileTime(eigen->getCompileTime());
};
BiNE2SteQR::BiNE2SteQR() : BiSVD( "NE2 dsteqr" ) {
	aUpper = true; 
	aLower = true; 
	aUColMajor = true; 
	aVColMajor = true; 
	eigen = new SteQR(); 
	setCompileTime(__DATE__, __TIME__);
	if (eigen) setCompileTime(eigen->getCompileTime());
};
//REGISTER(SteQR); 
//steqr is having weird behaviour
//REGISTER(BiNESteQR);
//REGISTER(BiNE2SteQR);
